package com.cneport.das.common.utils;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.concurrent.ConcurrentHashMap;

/**
 * <p>标题：实体类 与 xml 转换工具类</p>
 * <p>功能：</p>
 * <p>
 * 其他说明：
 * </p>
 * <p>作者：冯继亮</p>
 * <p>审核：</p>
 * <p>重构：</p>
 * <p>创建日期：2021/8/26 周四 9:48</p>
 * 查看帮助：<a href="" target="_blank"></a>
 */
public class JAXBUtils {

    /**
     * 创建JAXBContext开销较大，通过Map缓存，提高效率
     */
    private static ConcurrentHashMap<Class, JAXBContext> jaxbContMap
            = new ConcurrentHashMap<Class, JAXBContext>();

    public static <T> String obj2Xml(T t) {
        try {
            JAXBContext jc = getJaxbContext(t.getClass());
            Marshaller marshaller = jc.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");

            StringWriter writer = new StringWriter();
            marshaller.marshal(t, writer);
            return writer.toString();
        } catch (JAXBException ex) {
            ex.printStackTrace();
            throw new RuntimeException(ex);
        }
    }

    public static <T> T xml2Obj(Class<T> t, String xml) {
        try {
            JAXBContext jc = getJaxbContext(t);
            Unmarshaller marshaller = jc.createUnmarshaller();

            return (T) marshaller.unmarshal(new StringReader(xml));
        } catch (JAXBException ex) {
            ex.printStackTrace();
            throw new RuntimeException(ex);
        }
    }

    public static Object xml2Obj(String xml, String indexPackage) {
        try {
            JAXBContext jc = JAXBContext.newInstance(indexPackage);
            Unmarshaller marshaller = jc.createUnmarshaller();

            return marshaller.unmarshal(new StringReader(xml));
        } catch (JAXBException ex) {
            ex.printStackTrace();
            throw new RuntimeException(ex);
        }
    }

    private static <T> JAXBContext getJaxbContext(Class<T> t) throws JAXBException {
        JAXBContext jc = jaxbContMap.get(t);
        if (jc == null) {
            synchronized (t) {
                jc = JAXBContext.newInstance(t);
                jaxbContMap.put(t, jc);
            }
        }
        return jc;
    }

}
